package com.sghj.Interceptor;

import com.alibaba.fastjson.JSONObject;
import com.sghj.config.handler.ResultCode;
import com.sghj.config.handler.exceptionHandler.MyException;
import com.sghj.utils.JwtUtils;
import com.sghj.utils.StringUtils;
import io.jsonwebtoken.Jwts;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;


import static com.sghj.utils.JwtUtils.*;

//自定义拦截器类----》注入拦截器\
@Slf4j
public class AuthenticationInterceptor implements HandlerInterceptor {
    @Autowired
    private JwtUtils jwtutils;
    @Autowired
    private RedisTemplate redisTemplate;

    //prehandle:控制器方法前执行，返回值为true时，继续向下执行
    public boolean isExpired(HttpServletRequest request){

        return !jwtutils.checkToken(request);
    }
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
        //获取请求端
        String authorization = request.getHeader("Authorization");
        //如果是前台请求
        if (StringUtils.isNotEmpty(authorization)&&authorization.equals("token")) {
            //获取请求头携带的前台token
            String token = jwtutils.getToken(request);
            if (StringUtils.isNotEmpty(token)) {
                //检测token是否有效
                try {
                    Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(token);
                } catch (Exception e) {
                    throw new MyException(ResultCode.FAIL,"token无效");
                }

                //获取redis中缓存
                Integer id = jwtutils.getIdByToken(token);
                String redisToken = (String) redisTemplate.opsForValue().get("front_token:" + id);      //redis内token
                Long expire = redisTemplate.opsForValue().getOperations().getExpire("front_token:" + id);        //token有效期

                if (StringUtils.isEmpty(redisToken)) {
                    //log.info("登录id："+id);
                    //log.info("请求接口:"+request.getRequestURI());
                    //log.info("请求地址:"+request.getRequestURL());

                    throw new MyException(ResultCode.NEEDRELOGIN, "身份信息已过期，请重新登录");
                }
                if (!redisToken.equals(token)) {
                    throw new MyException(ResultCode.NEEDRELOGIN, "账号在别处登录");
                }
                //刷新token有效期
                if (expire<= MILLIS_MINUTE_TEN){
                    redisTemplate.opsForValue().set("front_token:" + id, redisToken, EXPIRE, TimeUnit.MILLISECONDS);
                }
                return true;
            }
            returnFailResult(response);
            return false;
        }
        //如果是后台
        else if (StringUtils.isNotEmpty(authorization)&&authorization.equals("zjcq_token"))
        {
            String manageToken  = jwtutils.getManageToken(request);
            if (jwtutils.checkToken(manageToken)){
                return true;
            }
            returnFailResult(response);
            log.info("非法token,当前token'{}'",manageToken);
            return false;
        }
        //如果其他端
        else {
            String token = jwtutils.getToken(request);
            if (jwtutils.checkToken(token)){
                return true;
            }
            log.info("限制无token请求");
            returnFailResult(response);
            return false;
        }
    }

    /**
     * 创建一个错误返回对象
     * @param response
     * @return
     * @throws IOException
     */
    public Map returnFailResult(HttpServletResponse response) throws IOException {
        PrintWriter writer = response.getWriter();
        Map result = new HashMap();
        result.put("success","false");
        result.put("code",ResultCode.GETTOKENERROR);
        result.put("message","Token validation failed");
        writer.println(JSONObject.toJSONString(result));
        writer.close();
        response.flushBuffer();
        return result;
    }
}